package com.wetao.testrxjava.retrofit;

import java.util.Map;

import io.reactivex.Observable;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.HTTP;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Part;
import retrofit2.http.PartMap;
import retrofit2.http.Path;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import retrofit2.http.Streaming;
import retrofit2.http.Url;

/**
 * Created by caihan on 2017/1/11.
 *
 * @GET 表明这是get请求
 * @POST 表明这是post请求
 * @PUT 表明这是put请求
 * @DELETE 表明这是delete请求
 * @PATCH 表明这是一个patch请求，该请求是对put请求的补充，用于更新局部资源
 * @HEAD 表明这是一个head请求
 * @OPTIONS 表明这是一个option请求
 * @HTTP 通用注解, 可以替换以上所有的注解，其拥有三个属性：method，path，hasBody
 * @Headers 用于添加固定请求头，可以同时添加多个。通过该注解添加的请求头不会相互覆盖，而是共同存在
 * @Header 作为方法的参数传入，用于添加不固定值的Header，该注解会更新已有的请求头
 * @Body 多用于post请求发送非表单数据, 比如想要以post方式传递json格式数据
 * @Filed 多用于post请求中表单字段, Filed和FieldMap需要FormUrlEncoded结合使用
 * @FiledMap 和@Filed作用一致，用于不确定表单参数
 * @Part 用于表单字段, Part和PartMap与Multipart注解结合使用, 适合文件上传的情况
 * @PartMap 用于表单字段, 默认接受的类型是Map<String,REquestBody>，可用于实现多文件上传
 * <p>
 * Part标志上文的内容可以是富媒体形势，比如上传一张图片，上传一段音乐，即它多用于字节流传输。
 * 而Filed则相对简单些，通常是字符串键值对。
 * </p>
 * Part标志上文的内容可以是富媒体形势，比如上传一张图片，上传一段音乐，即它多用于字节流传输。
 * 而Filed则相对简单些，通常是字符串键值对。
 * @Path 用于url中的占位符,{占位符}和PATH只用在URL的path部分，url中的参数使用Query和QueryMap代替，保证接口定义的简洁
 * @Query 用于Get中指定参数
 * @QueryMap 和Query使用类似
 * @Url 指定请求路径
 */

public interface  MyRetrofit2Service {
    //使用@Headers添加多个请求头
    @Headers({
            "User-Agent:android",
            "apikey:123456789",
    })

    @HTTP(method = "GET", path = "group/{id}/users",hasBody = false)
    Observable<String> groupList1(@Path("id") int groupId);


    @POST()
    Call<News> post(@Url String url, @QueryMap Map<String, String> map);

    @GET("mobile/active")
    Call<News> get(@Header("token") String token, @Query("id") int activeId);

    @GET("active/list")
    Call<News> ActiveList();

    @POST("api/news/newsList")
    Call<News> post2(@QueryMap Map<String, String> map);

    /**
     * 很多情况下，我们需要上传json格式的数据。比如当我们注册新用户的时候，因为用户注册时的数据相对较多，
     * 并可能以后会变化，这时候，服务端可能要求我们上传json格式的数据。此时就要@Body注解来实现。
     * 直接传入实体,它会自行转化成Json
     *
     * @param url
     * @param post
     * @return
     */
    @POST("api/{url}/newsList")
    Call<News> login(@Path("url") String url, @Body News post);

    @GET("group/{id}/users")
    Call<ResponseBody> groupList(@Path("id") int groupId);


    /**
     * 单张图片上传
     * retrofit 2.0的上传和以前略有不同，需要借助@Multipart注解、@Part和MultipartBody实现。
     *
     * @param url
     * @param file
     * @return
     */
    @Multipart
    @POST("{url}")
    Call<News> upload(@Path("url") String url, @Part MultipartBody.Part file);

    /**
     * 多张图片上传
     *
     * @param map
     * @return
     */
    @Multipart
    @POST("upload/upload")
    Call<News> upload(@PartMap Map<String, MultipartBody.Part> map);

    @Multipart
    @PUT("user/photo")
    Call<News> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);

    /**
     * 图文混传
     *
     * @param post
     * @param map
     * @return
     */
    @Multipart
    @POST("")
    Call<News> register(@Body News post, @PartMap Map<String, MultipartBody.Part> map);

    /**
     * 文件下载
     *
     * @param fileUrl
     * @return
     */
    @Streaming
    @GET
    Call<News> downloadPicture(@Url String fileUrl);

    /**
     * 这里需要注意的是如果下载的文件较大，比如在10m以上，那么强烈建议你使用@Streaming进行注解，否则将会出现IO异常.
     *
     * @param fileUrl
     * @return
     */
    @Streaming
    @GET
    Observable<News> downloadPicture2(@Url String fileUrl);

    @POST()
    @FormUrlEncoded
    Observable<News> executePost(@FieldMap Map<String, Object> maps);


    @FormUrlEncoded
    @POST("user/edit")
    Call<News> updateUser(@Field("first_name") String first, @Field("last_name") String last);
	
	
	//@Header用于添加不固定的请求头，作用于方法的参数，作为方法的参数传入，该注解会更新已有的请求头。
	@GET("user/emails")
	Call<ResponseBody> getHeaderData(@Header("token") String token);
	
	//@Headers用于添加固定的请求头，作用于方法，可以同时添加多个，通过该注解添加的请求头不会相互覆盖，而是共同存在。
	@Headers({"phone-type:android", "version:1.1.1"})
	@GET("user/emails")
	Call<ResponseBody> getHeadersData();

    //@Multipart  表示请求实体是一个支持文件上传的表单，需要配合@Part和@PartMap使用，适用于文件上传
    //@Part       用于表单字段，适用于文件上传的情况，@Part支持三种类型：RequestBody、MultipartBody.Part、                                       任意类型
    //@PartMap    用于多文件上传， 与@FieldMap和@QueryMap的使用类似
    @Multipart
    @POST("user/followers")
    Call<ResponseBody> getPartData(@Part("name") RequestBody name, @Part MultipartBody.Part file);

    //@PartMap的使用与@FieldMap和@QueryMap的使用类似，用于多文件上传
    @Multipart
    @POST("user/followers")
    Call<ResponseBody> getPartMapData(@PartMap Map<String, MultipartBody.Part> map);

}
